home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1997 February
/
EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso
/
enigma
/
earcd
/
utility
/
utilgraf
/
newicndt.lha
/
NewIconDT
/
Sources
/
dispatch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-10-25
|
21KB
|
774 lines
//;--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T--T
/******************************************************************************
*
* NewIcon Datatype
*
* Written by Pascal Hurni and Christian Buchner and David N. Junod
*
******************************************************************************
* dispatch.c
*
*/
/************************************************************************
* *
* Prefs: *
* NOBORDER/S Dont' draw the border around images. *
* NONORMAL/S Dont' include the normal state image. *
* NOSELECTED/S Dont' include the selected state image. *
* XOFFSET/N Defines the number of pixels between the horizontal*
* borders and the images. Default to 2. *
* YOFFSET/N Defines the number of pixels between the vertical *
* borders and the images. Default to 2. *
* BORDERPEN/N The pen number used to draw the border. Default *
* to 1. *
* COLORMAP A picture filename containing a colormap. The *
* images will be remaped to this colormap. *
* *
************************************************************************/
//#define DEBUG
#include "debug.h"
#include "classbase.h"
/*****************************************************************************/
void MineWriteChunkyPixels( struct RastPort *rp, LONG xstart, LONG ystart,
LONG xstop, LONG ystop, UBYTE *array, LONG bytesperrow,
UBYTE *convtable, LONG flags,
struct ClassBase *cb );
UBYTE MyObtainBestPen( struct ColorRegister color, struct ColorRegister *cmap,
UWORD ncol );
Object *GetFileColorMap( STRPTR filename, struct ColorRegister **pt_cmap, ULONG *pt_ncolors,
struct ClassBase *cb );
void FreeFileColorMap( Object *obj, struct ClassBase *cb );
#define PREFSTEMPLATE "NOBORDER/S,NONORMAL/S,NOSELECTED/S,XOFFSET/N,YOFFSET/N,BORDERPEN/N,COLORMAP"
enum {
PREFSARG_NOBORDER,
PREFSARG_NONORMAL,
PREFSARG_NOSELECTED,
PREFSARG_XOFFSET,
PREFSARG_YOFFSET,
PREFSARG_BORDERPEN,
PREFSARG_COLORMAP,
PREFSARG_MAX
};
/*****************************************************************************/
ULONG setdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
{
return (SetDTAttrsA (o, NULL, NULL, (struct TagItem *) & data));
}
/*****************************************************************************/
ULONG getdtattrs (struct ClassBase * cb, Object * o, ULONG data,...)
{
return (GetDTAttrsA (o, (struct TagItem *) & data));
}
/*****************************************************************************/
Class *initClass (struct ClassBase * cb)
{
Class *cl;
/* Create our class. Note that this particular class doesn't have any instance data */
if (cl = MakeClass (NEWICONDTCLASS, PICTUREDTCLASS, NULL, NULL, 0L))
{
cl->cl_Dispatcher.h_Entry = (ULONG (*)())Dispatch;
cl->cl_UserData = (ULONG) cb;
AddClass (cl);
}
return (cl);
}
/*****************************************************************************/
ULONG __asm Dispatch (register __a0 Class * cl, register __a2 Object * o, register __a1 Msg msg)
{
struct ClassBase *cb = (struct ClassBase *) cl->cl_UserData;
ULONG retval;
switch (msg->MethodID)
{
case OM_NEW:
if (retval = DoSuperMethodA (cl, o, msg))
{
if (!GetPicture (cb, cl, (Object *) retval, ((struct opSet *) msg)->ops_AttrList))
{
CoerceMethod (cl, (Object *) retval, OM_DISPOSE);
return NULL;
}
}
break;
/* Let the superclass handle everything else */
default:
retval = (ULONG) DoSuperMethodA (cl, o, msg);
break;
}
return (retval);
}
/*****************************************************************************/
BOOL __asm GetPicture (register __a6 struct ClassBase * cb, register __a0 Class * cl, register __a2 Object * o, register __a1 struct TagItem * attrs)
{
BOOL success = FALSE;
STRPTR title;
STRPTR fname;
struct BitMapHeader *bmhd;
struct BitMap *bm;
UWORD i, n, ncolors;
ULONG modeid = VGAPRODUCT_KEY;
struct ColorRegister *cmap, *tmpcmap;
LONG *cregs;
ULONG TmpOffset;
ULONG XOffset = 2;
ULONG YOffset = 2;
UWORD BorderPen = 1;
struct NewDiskObject *ndo;
ULONG depth, rest;
STRPTR tmp;
struct RastPort rp;
Point PolyDrawArray[4];
UBYTE *ConvTable;
Object *obj;
BPTR fh;
struct ColorRegister *var_ColorMap = NULL;
ULONG var_NColors;
ULONG var_Border = TRUE;
ULONG var_Normal = TRUE;
ULONG var_Selected = TRUE;
ENTERING;
/* Get the default title */
title = (STRPTR) GetTagData (DTA_Name, NULL, attrs);
/* create the filename */
if ( !(fname = AllocVec( strlen( title ) , 0L ) ) ) {
SetIoErr(ERROR_NO_FREE_STORE);
}
else {
strcpy( fname, title );
if ( !((tmp = strrchr( fname, '.' )) && (strcmp( tmp, ".info" ) == 0)) ) {
SetIoErr(ERROR_INVALID_COMPONENT_NAME);
}
else {
*tmp = 0;
/* Get the BitMapHeader to write to */
if ( getdtattrs (cb, o, PDTA_BitMapHeader, &bmhd, TAG_DONE) != 1 )
{
SetIoErr(ERROR_OBJECT_WRONG_TYPE);
}
else
{
DPUT(("About to get prefs vars.\n" ));
/*** Get the environement variables for the preferences */
/* Opens the prefs file */
if ( fh = Open( "ENV:Datatypes/NewIcon.prefs", MODE_OLDFILE ) ) {
struct RDArgs *rdargs;
UBYTE buf[256];
ULONG para[PREFSARG_MAX];
DPUT(("Prefs file opened.\n" ));
/* Get next line */
while ( FGets( fh, buf, sizeof(buf) ) ) {
/* Process it if it's not a comment */
tmp = buf;
while ( *tmp < 33 && *tmp != 0 ) tmp++;
if ( !((*tmp == ';') || (*tmp == '#') || (*tmp == '*') || (*tmp == 0)) ) {
if ( rdargs = (struct RDArgs *)AllocDosObject( DOS_RDARGS, NULL ) ) {
rdargs->RDA_Source.CS_Buffer = buf;
rdargs->RDA_Source.CS_Length = strlen(buf);
para[PREFSARG_NOBORDER] = FALSE;
para[PREFSARG_NONORMAL] = FALSE;
para[PREFSARG_NOSELECTED] = FALSE;
para[PREFSARG_XOFFSET] = NULL;
para[PREFSARG_YOFFSET] = NULL;
para[PREFSARG_BORDERPEN] = NULL;
para[PREFSARG_COLORMAP] = NULL;
if ( ReadArgs( PREFSTEMPLATE, (LONG *) para, rdargs) ) {
if ( para[PREFSARG_NOBORDER] )
var_Border = FALSE;
if ( para[PREFSARG_NONORMAL] )
var_Normal = FALSE;
if ( para[PREFSARG_NOSELECTED] )
var_Selected = FALSE;
if ( para[PREFSARG_XOFFSET] ) {
XOffset = *((LONG *) para[PREFSARG_XOFFSET]);
if ( XOffset > 65535 ) XOffset = 2;
}
if ( para[PREFSARG_YOFFSET] ) {
YOffset = *((LONG *) para[PREFSARG_YOFFSET]);
if ( YOffset > 65535 ) YOffset = 2;
}
if ( para[PREFSARG_BORDERPEN] ) {
BorderPen = (*((LONG *) para[PREFSARG_BORDERPEN])) & 255;
}
if ( para[PREFSARG_COLORMAP] ) {
obj = GetFileColorMap( (STRPTR)para[PREFSARG_COLORMAP], &var_ColorMap, &var_NColors, cb );
}
}
FreeDosObject( DOS_RDARGS, rdargs );
}
}
}
Close( fh );
}
DPUT(("About to GetNewDiskObject() with fname=[%s]\n", fname ));
if ( ndo = GetNewDiskObject( fname ) ) {
DPUT(("GetNewDiskObject() successful !\n" ));
if ( (ndo->ndo_NormalImage != NULL && var_Normal) || (ndo->ndo_SelectedImage != NULL && var_Selected) ) {
/*** Computes the BitMap dimensions */
bmhd->bmh_Width = XOffset;
bmhd->bmh_Height = 0;
if ( ndo->ndo_NormalImage && var_Normal ) {
bmhd->bmh_Width += ndo->ndo_NormalImage->Width+XOffset;
bmhd->bmh_Height = ndo->ndo_NormalImage->Height;
if ( var_Border )
bmhd->bmh_Width += 1+1;
DPUT(("NormalImage: Width=%ld, Height=%ld\n", (LONG)ndo->ndo_NormalImage->Width, (LONG)ndo->ndo_NormalImage->Height ));
}
if ( ndo->ndo_SelectedImage && var_Selected ) {
bmhd->bmh_Width += ndo->ndo_SelectedImage->Width+XOffset;
bmhd->bmh_Height = MAX( ndo->ndo_NormalImage->Height, bmhd->bmh_Height );
if ( var_Border )
bmhd->bmh_Width += 1+1;
DPUT(("SelectedImage: Width=%ld, Height=%ld\n", (LONG)ndo->ndo_SelectedImage->Width, (LONG)ndo->ndo_SelectedImage->Height ));
}
bmhd->bmh_Height += YOffset+YOffset;
if ( var_Border )
bmhd->bmh_Height += 1+1;
/*** Get the number of different colors in both image */
if ( var_ColorMap ) {
ncolors = var_NColors;
}
else {
if ( !ndo->ndo_NormalImage || !var_Normal ) {
ncolors = ndo->ndo_SelectedImage->NumColors;
}
else if ( !ndo->ndo_SelectedImage || !var_Selected ) {
ncolors = ndo->ndo_NormalImage->NumColors;
}
else {
ncolors = ndo->ndo_NormalImage->NumColors;
for ( n=0; n<ndo->ndo_SelectedImage->NumColors; n++ ) {
for ( i=0; i<ndo->ndo_NormalImage->NumColors; i++ ) {
if ( *((struct ColorRegister *) &(ndo->ndo_NormalImage->Palette[i*3])) ==
*((struct ColorRegister *) &(ndo->ndo_SelectedImage->Palette[n*3])) ) {
ncolors--;
break;
}
}
ncolors++;
}
}
}
/*** Calculate the depth according to ncolors */
depth = 0;
rest = ncolors-1;
while ( rest > 0 ) {
rest = rest >> 1;
depth++;
}
if ( depth == 0 ) depth = 1; /*** If ncolors was 1 */
if ( depth > 8 ) {
depth = 8; /*** If ncolors was greater than 256 */
ncolors = 256;
}
bmhd->bmh_Depth = depth;
DPUT(("BMHD: Width=%ld, Height=%ld, NColors=%ld, Depth=%ld\n",
(LONG)bmhd->bmh_Width, (LONG)bmhd->bmh_Height, (LONG)ncolors, (LONG)bmhd->bmh_Depth ));
/* Set the number of colors */
setdtattrs (cb, o, PDTA_NumColors, ncolors, TAG_DONE);
/* Get the destination for the color information */
getdtattrs (cb, o,
PDTA_ColorRegisters, (ULONG) &cmap,
PDTA_CRegs, &cregs,
TAG_DONE);
/*** Set up the Colormap for both images */
if ( var_ColorMap ) {
DPUT(("The ColorMap :"));
tmpcmap = cmap;
for ( n=0; n<ncolors; n++ ) {
/* Set the master color table */
tmpcmap->red = var_ColorMap->red;
tmpcmap->green = var_ColorMap->green;
tmpcmap->blue = var_ColorMap->blue;
/* Set the color table used for remapping */
cregs[n * 3 + 0] = tmpcmap->red << 24;
cregs[n * 3 + 1] = tmpcmap->green << 24;
cregs[n * 3 + 2] = tmpcmap->blue << 24;
D(if ( (n % 8) == 0 ) bprintf("\n") );
DPUT(("%02lx%02lx%02lx ", (LONG) tmpcmap->red, (LONG) tmpcmap->green, (LONG) tmpcmap->blue ));
tmpcmap++;
var_ColorMap++;
}
DPUT(("\n\n"));
/*** Frees the file colormap */
FreeFileColorMap( obj, cb );
}
else {
if ( !ndo->ndo_NormalImage ) {
memcpy( cmap, ndo->ndo_SelectedImage->Palette, ndo->ndo_SelectedImage->NumColors * 3 );
}
else if ( !ndo->ndo_SelectedImage ) {
memcpy( cmap, ndo->ndo_NormalImage->Palette, ndo->ndo_NormalImage->NumColors * 3 );
}
else {
memcpy( cmap, ndo->ndo_NormalImage->Palette, ndo->ndo_NormalImage->NumColors * 3 );
tmpcmap = cmap+ndo->ndo_NormalImage->NumColors;
/*** BUG: It can happen that NormalImage->NumColors plus the different
*** colors in SelectedImage could exceeds 256 ! A check should be done
*** inside the for loop below.
**/
for ( n=0; n<ndo->ndo_SelectedImage->NumColors; n++ ) {
for ( i=0; i<ndo->ndo_NormalImage->NumColors; i++ ) {
if ( *((struct ColorRegister *) &(ndo->ndo_NormalImage->Palette[i*3])) ==
*((struct ColorRegister *) &(ndo->ndo_SelectedImage->Palette[n*3])) ) {
break;
}
}
if ( i == ndo->ndo_NormalImage->NumColors ) {
*tmpcmap = *((struct ColorRegister *) &(ndo->ndo_SelectedImage->Palette[n*3]));
tmpcmap++;
}
}
}
DPUT(("The ColorMap :"));
tmpcmap = cmap;
for ( n=0; n<ncolors; n++ ) {
D(if ( (n % 8) == 0 ) bprintf("\n") );
DPUT(("%02lx%02lx%02lx ", (LONG) tmpcmap->red, (LONG) tmpcmap->green, (LONG) tmpcmap->blue ));
/* Set the color table used for remapping */
cregs[n * 3 + 0] = tmpcmap->red << 24;
cregs[n * 3 + 1] = tmpcmap->green << 24;
cregs[n * 3 + 2] = tmpcmap->blue << 24;
tmpcmap++;
}
DPUT(("\n\n"));
}
/* Allocate the bitmap and the memory for the convtable */
if ( ( (bm = AllocBitMap (bmhd->bmh_Width, bmhd->bmh_Height, bmhd->bmh_Depth, BMF_CLEAR, NULL)) == NULL ) ||
( (ConvTable = AllocVec( ncolors, 0L ) ) == NULL ) ) {
FreeBitMap( bm );
FreeVec( ConvTable );
SetIoErr (ERROR_NO_FREE_STORE);
}
else
{
/* Indicate success */
success = TRUE;
/*** Set up the RastPort */
InitRastPort( &rp );
rp.BitMap = bm;
if ( ndo->ndo_NormalImage && var_Normal ) {
if ( var_Border ) {
/*** Draws the border for the Normal image */
SetAPen( &rp, BorderPen );
Move( &rp, XOffset, YOffset );
PolyDrawArray[0].x = XOffset+ndo->ndo_NormalImage->Width+1;
PolyDrawArray[0].y = YOffset;
PolyDrawArray[1].x = XOffset+ndo->ndo_NormalImage->Width+1;
PolyDrawArray[1].y = YOffset+ndo->ndo_NormalImage->Height+1;
PolyDrawArray[2].x = XOffset;
PolyDrawArray[2].y = YOffset+ndo->ndo_NormalImage->Height+1;
PolyDrawArray[3].x = XOffset;
PolyDrawArray[3].y = YOffset;
PolyDraw( &rp, 4, (WORD *)PolyDrawArray );
}
/*** Computes the ConvTable for the Normal image */
DPUT(("ConvTable for Normal image\n"));
for ( i=0; i<ndo->ndo_NormalImage->NumColors; i++ ) {
ConvTable[i] = MyObtainBestPen( *((struct ColorRegister *) &(ndo->ndo_NormalImage->Palette[i*3])),
cmap, ncolors );
DPUT(("ConvTable[%ld] = %ld for color = %02lx%02lx%02lx\n",
(LONG) i, (LONG) ConvTable[i],
(LONG) ndo->ndo_NormalImage->Palette[i*3],
(LONG) ndo->ndo_NormalImage->Palette[i*3+1],
(LONG) ndo->ndo_NormalImage->Palette[i*3+2] ));
}
/*** Copy the Normal image */
if ( !var_Border ) {
XOffset--;
YOffset--;
}
MineWriteChunkyPixels( &rp, XOffset+1, YOffset+1,
XOffset+ndo->ndo_NormalImage->Width,
YOffset+ndo->ndo_NormalImage->Height,
ndo->ndo_NormalImage->ChunkyData,
ndo->ndo_NormalImage->Width,
ConvTable,
ndo->ndo_NormalImage->Flags,
cb );
if ( !var_Border ) {
XOffset++;
YOffset++;
}
TmpOffset = XOffset+ndo->ndo_NormalImage->Width+XOffset;
if ( var_Border )
TmpOffset += 2;
}
else {
TmpOffset = XOffset;
}
if ( ndo->ndo_SelectedImage && var_Selected ) {
if ( var_Border ) {
/*** Draws the border for the Selected image */
SetAPen( &rp, BorderPen );
Move( &rp, TmpOffset, YOffset );
PolyDrawArray[0].x = TmpOffset+ndo->ndo_SelectedImage->Width+1;
PolyDrawArray[0].y = YOffset;
PolyDrawArray[1].x = TmpOffset+ndo->ndo_SelectedImage->Width+1;
PolyDrawArray[1].y = YOffset+ndo->ndo_SelectedImage->Height+1;
PolyDrawArray[2].x = TmpOffset;
PolyDrawArray[2].y = YOffset+ndo->ndo_SelectedImage->Height+1;
PolyDrawArray[3].x = TmpOffset;
PolyDrawArray[3].y = YOffset;
PolyDraw( &rp, 4, (WORD *)PolyDrawArray );
}
/*** Computes the ConvTable for the Selected image */
DPUT(("\nConvTable for Selected image\n"));
for ( i=0; i<ndo->ndo_SelectedImage->NumColors; i++ ) {
ConvTable[i] = MyObtainBestPen( *((struct ColorRegister *) &(ndo->ndo_SelectedImage->Palette[i*3])),
cmap, ncolors );
DPUT(("ConvTable[%ld] = %ld for color = %02lx%02lx%02lx\n",
(LONG) i, (LONG) ConvTable[i],
(LONG) ndo->ndo_SelectedImage->Palette[i*3],
(LONG) ndo->ndo_SelectedImage->Palette[i*3+1],
(LONG) ndo->ndo_SelectedImage->Palette[i*3+2] ));
}
/*** Copy the Selected image */
if ( !var_Border ) {
TmpOffset--;
YOffset--;
}
MineWriteChunkyPixels( &rp, TmpOffset+1, YOffset+1,
TmpOffset+ndo->ndo_SelectedImage->Width,
YOffset+ndo->ndo_SelectedImage->Height,
ndo->ndo_SelectedImage->ChunkyData,
ndo->ndo_SelectedImage->Width,
ConvTable,
ndo->ndo_SelectedImage->Flags,
cb );
}
if (success)
{
/* Set the attributes */
setdtattrs (cb, o,
DTA_ObjName, title,
DTA_NominalHoriz, bmhd->bmh_Width,
DTA_NominalVert, bmhd->bmh_Height,
GA_Width, bmhd->bmh_Width,
GA_Height, bmhd->bmh_Height,
PDTA_BitMap, bm,
PDTA_ModeID, modeid,
TAG_DONE);
}
else
{
/* Free the bitmap on failure */
FreeBitMap(bm);
}
FreeVec( ConvTable );
}
}
FreeNewDiskObject( ndo );
}
}
}
FreeVec( fname );
}
DPUT(("\nReturning with success=%ld\n", (LONG)success));
LEAVING;
return (success);
}
/*****************************************************************************/
void MineWriteChunkyPixels( struct RastPort *rp, LONG xstart, LONG ystart,
LONG xstop, LONG ystop, UBYTE *array, LONG bytesperrow,
UBYTE *convtable, LONG flags,
struct ClassBase *cb ) {
/* Actually, bytesperrow is ignored */
LONG x,y;
for ( y=ystart; y<=ystop; y++ ) {
for ( x=xstart; x<=xstop; x++ ) {
SetAPen( rp, convtable[*array++] );
WritePixel( rp, x, y );
}
}
}
/*****************************************************************************/
UBYTE MyObtainBestPen( struct ColorRegister color, struct ColorRegister *cmap,
UWORD ncol ) {
UWORD red, green, blue;
UWORD i;
UWORD pen;
UWORD prox;
UWORD oldprox = 0xFFFF;
red = color.red << 4;
green = color.green << 4;
blue = color.blue << 4;
for ( i=0; i<ncol; i++ ) {
if ( (prox = TestProximity( cmap->red << 4 , cmap->green << 4 , cmap->blue << 4 ,
red, green, blue ) ) == 0 ) {
return (UBYTE)i;
}
if ( prox < oldprox ) {
oldprox = prox;
pen = i;
}
cmap++;
}
return (UBYTE)pen;
}
/*****************************************************************************/
Object *GetFileColorMap( STRPTR filename, struct ColorRegister **pt_cmap, ULONG *pt_ncolors,
struct ClassBase *cb ) {
struct DataType *dt;
BPTR fl;
Object *obj = NULL;
if ( fl = Lock( filename, ACCESS_READ ) ) {
if ( dt = ObtainDataTypeA( DTST_FILE, (APTR)fl, NULL ) ) {
if ( dt->dtn_Header->dth_GroupID == GID_PICTURE ) {
ReleaseDataType( dt );
/*** At this point we are sure that 'filename' is a picture */
/* get the picture object */
if ( obj = NewDTObject( filename,
DTA_SourceType, DTST_FILE,
DTA_GroupID, GID_PICTURE,
PDTA_Remap, FALSE,
TAG_DONE) ) {
if ( GetDTAttrs( obj, PDTA_ColorRegisters, pt_cmap,
PDTA_NumColors, pt_ncolors ) != 2 ) {
DisposeDTObject( obj );
obj = NULL;
*pt_cmap = NULL;
}
DPUT(("ColorMap got: ncolors = %ld, cmap = %lx\n", (LONG) *pt_ncolors, (LONG) *pt_cmap ));
}
}
else
ReleaseDataType( dt );
}
UnLock( fl );
}
return obj;
}
/*****************************************************************************/
void FreeFileColorMap( Object *obj, struct ClassBase *cb ) {
DisposeDTObject( obj );
}